package com.ltmonitor.server.mina;

import java.net.InetSocketAddress;
import java.util.Collection;

import org.apache.log4j.Logger;
import org.apache.mina.core.future.WriteFuture;
import org.apache.mina.core.service.IoAcceptor;
import org.apache.mina.core.service.IoHandler;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.core.session.IoSessionConfig;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.ltmonitor.app.GlobalConfig;
import com.ltmonitor.app.GpsConnection;
import com.ltmonitor.jt808.service.IJT808Server;

/**
 * 808Tcp服务
 *
 */
@Service("jt808TcpMinaServer")
public class JT808TcpServer implements IJT808Server {
	private static Logger logger = Logger.getLogger(JT808TcpServer.class);
	public static boolean isOpen = false;

	private IJT808Server instance = null;
	
	private int port;

	public IoAcceptor dataAccepter = null;
	@Autowired
	private IJT808ServerHandler jt808ServerHandler;
	public void Stop()
	{
		if (null!=dataAccepter) {  
			dataAccepter.unbind();  
			dataAccepter.getFilterChain().clear();  
			dataAccepter.dispose();                 
			dataAccepter = null;  
        }  
	}
	
	/**
	 * 获取当前所有的连接
	 */
	public Collection<GpsConnection> getGpsConnections()
	{
		return jt808ServerHandler.getConnections();
	}
	
	@Override
	public boolean isOnline(String simNo)
	{
		if(simNo == null || simNo.length() == 0)
		{
			logger.error(simNo+"为空，不能获得连接信息");
			return false;
		}
		GpsConnection conn = this.jt808ServerHandler.getConnection(simNo);
		if(conn != null)
		{
			IoSession session = getSession(conn.getSessionId());
			if(session == null)
			{
				logger.error(simNo+"会话session为空");				
			}else if(session.isConnected() == false)
			{
				logger.error(simNo+"session连接状态位false");	
			}
			return session != null && session.isConnected() ;
		}else
		{
			logger.error(simNo+"找不到连接，判断位不上线");
		}
		return false;
	}

	/**
	 * 发送字节流数据
	 */
	public boolean send(String simNo, byte[] msg)
	{
		GpsConnection conn = this.jt808ServerHandler.getConnection(simNo);
		if(conn != null)
			return send(conn.getSessionId(), msg);
		return false;
	}
	
	public  boolean send(long sessionId, byte[] msg) {
		try {
			IoSession session = getSession(sessionId);
			if (session != null && session.isConnected()) {
				WriteFuture wf = session.write(msg);
				wf.awaitUninterruptibly(1000);
				if(wf.isWritten())
					return true;
				else
				{
					Throwable tr = wf.getException();
					if(tr != null)
					{
						logger.error(tr.getMessage(), tr);
					}
						
					return false;
				}
					
			}
		} catch (Exception ex) {
			logger.error(ex.getMessage(), ex);
		}
		return false;
	}
	

	
	public IoSession getSession(long sid)
	{
		return dataAccepter.getManagedSessions().get(sid);
	}

	
	public boolean start() {
		port = GlobalConfig.listenPort;
		try {
			dataAccepter = new NioSocketAcceptor();

			dataAccepter.getFilterChain().addLast("codec",
					new ProtocolCodecFilter(new JT808MessageCodecFactory()));

			IoSessionConfig config = dataAccepter.getSessionConfig();

			config.setReadBufferSize(4096);
			config.setWriteTimeout(40000);  
	        config.setWriterIdleTime(400000);  

			config.setIdleTime(IdleStatus.BOTH_IDLE, 70000);

			dataAccepter.setHandler((IoHandler)this.jt808ServerHandler);

			dataAccepter.bind(new InetSocketAddress(port));
			isOpen = true;
		} catch (Exception e) {
			isOpen = false;
			logger.error("808服务器启动失败:" + e.getMessage(), e);
			e.printStackTrace();
		}
		return isOpen;
	}


	public void setPort(int port) {
		this.port = port;
	}

	public int getPort() {
		return port;
	}
}
